#include <SPI.h>
#include "../ArduboyMod.h"

#include <EEPROM.h>

#include <avr/pgmspace.h>

Arduboy arduboy;

// frame counter
unsigned int frame = 0;

// general use string buffer
char text[16];



PROGMEM const unsigned char cactus_1[] =
// w:  12  h:  24
{ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xfe, 0x00, 0xc0, 0xc0, 0x80, 0xfe, 0xff, 0xfe, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0x7f, 0x01, 0x03, 0x03, 0x83, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00 };

// cloud_1 w:  17  h:  7
PROGMEM const unsigned char cloud_1[] =
{ 0x1c, 0x22, 0x22, 0x22, 0x24, 0x10, 0x12, 0x2a, 0x21, 0x41, 0x41, 0x41, 0x42, 0x4a, 0x24, 0x24, 0x18 };
 

PROGMEM const unsigned char dino_up[] ={
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe, 0xf6, 0xfe, 0xfe, 0x7e, 0x7e, 0x7e, 0x7e, 0x7c, 0x00, 0x00, 0xfc, 0xf0, 0xe0, 0xc0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x09, 0x19, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0xff, 0xbf, 0x1f, 0x0f, 0x1f, 0xff, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

// w:  30  h:  18
PROGMEM const unsigned char dino_tumble[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xf8, 0xf0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0xf0, 0xa8, 0xd8, 0xa8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf0, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01 };



// top w:  20  h:  18
PROGMEM const unsigned char dino_top[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xfb, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0x3f, 0x3e, 0x7e, 0xf8, 0xf0, 0xe0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

// leg_0 w:  20  h:  5
PROGMEM const unsigned char dino_leg_0[] =
{ 0x00, 0x00, 0x00, 0x00, 0x01, 0x1f, 0x17, 0x03, 0x01, 0x03, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

// leg_1 w:  20  h:  5
PROGMEM const unsigned char dino_leg_1[] =
{ 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x0b, 0x01, 0x01, 0x03, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

// leg_2 w:  20  h:  5
PROGMEM const unsigned char dino_leg_2[] =
{ 0x00, 0x00, 0x00, 0x00, 0x01, 0x1f, 0x17, 0x03, 0x01, 0x03, 0x0f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

void intro()
{
  for(int i = -8; i < 28; i = i + 2)
  {
    arduboy.clearDisplay();
    arduboy.setCursor(46, i);
    arduboy.print("ARDUBOY");
    arduboy.display();
    delay(16);
  }

  arduboy.tunes.tone(987, 120);
  delay(120);
  arduboy.tunes.tone(1318, 400);

  arduboy.setCursor(42, 48);
  arduboy.print("presents");
  arduboy.display();

  delay(2000);

  arduboy.tunes.tone(1318, 1);
}



// distance ran
int d, delta;

int cloud_1_y;

int d_jump, d_jump_t;

int d_run;
int d_tumble_t;

int ox;

void setup()
{
  arduboy.start();
  arduboy.setFrameRate(60);
  intro();
  d = 0;
  delta = 0;

  cloud_1_y = 2;

  d_jump = 0;
  d_jump_t = 0;

  d_tumble_t = 0;
  d_run = 0;

  ox = 130;
}

void loop()
{
  if (!arduboy.nextFrame()) return;

  if (!d_run && arduboy.pressed(B_BUTTON)) {
    d_run = 1;
  }

  if (d_tumble_t && arduboy.pressed(B_BUTTON)) {
    setup();
    return;
  }

  ++frame;
  if (frame>16000) frame = 0;

  // increase distance whilst running
  if (d_run && (++delta > 4)) {
    delta = 0; ++d; 
  }

  // obstacles
  if (d_run) {
    ox -= (frame%2)*(d/100) + 2;
    if (ox < -15) ox += 140 + random(0,60);
  }

  // jump!
  if (!d_jump_t && arduboy.pressed(B_BUTTON)) {
    d_jump_t = 1;
    d_jump=5;

    arduboy.tunes.tone(440, 40);

  } else if (d_jump_t) {
    if (d_jump_t == 3) arduboy.tunes.tone(880, 80);

    ++d_jump_t;

    if (d_jump_t<6) {
      d_jump +=6;
    } else if (d_jump_t<9) {
      d_jump +=2;
    } else if (d_jump_t<13) {
      d_jump +=1;
    } else if (d_jump_t == 16 || d_jump_t == 18) {
      d_jump +=1;
    } else if (d_jump_t == 20 || d_jump_t == 22) {
      d_jump -=1;
    } else if (d_jump_t>38) {
      d_jump = 0;
      d_jump_t = 0;
    } else if (d_jump_t>32) {
      d_jump -=6;
    } else if (d_jump_t>29) {
      d_jump -=2;
    } else if (d_jump_t>25) {
      d_jump -=1;
    }
  }

  // hit detect
  if (!d_tumble_t && ox > -10 && ox <16 && d_jump_t < 14) {
    d_tumble_t = 1;    
  }

  if (d_tumble_t) {
    if (d_tumble_t == 1) {
      arduboy.tunes.tone(246, 80);
    } else if (d_tumble_t == 6) {
      arduboy.tunes.tone(174, 200);
    }

    ++d_tumble_t;
    if (d_jump > -4) {
      d_jump -= 1;
      ox -= 1;
    } else {
      d_run = 0;
    }
  }

  arduboy.clearDisplay();


  // hud
  arduboy.setCursor(100, 0);
  sprintf(text,"%d",d);
  arduboy.print(text);


  // parallax clouds
  arduboy.drawBitmap(128 -(d%128),cloud_1_y,cloud_1,17,7,WHITE);

  if (d%128 == 0) {
    cloud_1_y = random(0,10);
  }

  // terrain
  if (d_jump > 4) {
    arduboy.drawLine(0,60,127,60,WHITE);
  } else {
    arduboy.drawLine(0,60,3,60,WHITE);
    arduboy.drawLine(12,60,127,60,WHITE); 
  }

  // obstacles
  arduboy.drawBitmap(ox,40,cactus_1,12,24,WHITE);

  // dino
  int dy = 40-d_jump;

  // tumbles!
  if (d_tumble_t) {
    arduboy.drawBitmap(0,dy,dino_tumble,30,18,WHITE);

  // runs!
  } else {
    arduboy.drawBitmap(0,dy,dino_top,20,18,WHITE);
  
    // Run, Dino, Run!
    if (d_run && !d_jump) {
      if ((frame%8)/4) {
        arduboy.drawBitmap(0,dy+18,dino_leg_1,20,5,WHITE);
      } else {
        arduboy.drawBitmap(0,dy+18,dino_leg_2,20,5,WHITE);
      }
    } else {
      arduboy.drawBitmap(0,dy+18,dino_leg_0,20,5,WHITE);
    }
  }

  arduboy.display();
  delay(16);
}
